Trò chơi Tic-Tac-Toe, game đánh caro full source code
- PickupCamera.cs
- Scripts /
- DemoPickup /
- Demos /
- Photon Unity Networking /
- Assets /
- project /
2 using System.Collections;
3
4
5 public class PickupCamera : Photon.MonoBehaviour
6 {
7
8 public Transform cameraTransform;
9 private Transform _target;
10
11 // The distance in the x-z plane to the target
12
13 public float distance = 7.0f;
14
15 // the height we want the camera to be above the target
16 public float height = 3.0f;
17
18 public float angularSmoothLag = 0.3f;
19 public float angularMaxSpeed = 15.0f;
20
21 public float heightSmoothLag = 0.3f;
22
23 public float snapSmoothLag = 0.2f;
24 public float snapMaxSpeed = 720.0f;
25
26 public float clampHeadPositionScreenSpace = 0.75f;
27
28 public float lockCameraTimeout = 0.2f;
29
30 private Vector3 headOffset = Vector3.zero;
31 private Vector3 centerOffset = Vector3.zero;
32
33 private float heightVelocity = 0.0f;
34 private float angleVelocity = 0.0f;
35 private bool snap = false;
36 private PickupController controller;
37 private float targetHeight = 100000.0f;
38
39 private Camera m_CameraTransformCamera;
40
41 void OnEnable()
42 {
43 if( this.photonView != null && !this.photonView.isMine )
44 {
45 this.enabled = false;
46 return;
47 }
48
49 if( !cameraTransform && Camera.main )
50 cameraTransform = Camera.main.transform;
51 if( !cameraTransform )
52 {
53 Debug.Log( "Please assign a camera to the ThirdPersonCamera script." );
54 enabled = false;
55 }
56
57 m_CameraTransformCamera = cameraTransform.GetComponent<Camera>();
58
59
60 _target = transform;
61 if( _target )
62 {
63 controller = _target.GetComponent<PickupController>();
64 }
65
66 if( controller )
67 {
68 CharacterController characterController = (CharacterController)_target.GetComponent<Collider>();
69 centerOffset = characterController.bounds.center - _target.position;
70 headOffset = centerOffset;
71 headOffset.y = characterController.bounds.max.y - _target.position.y;
72 }
73 else
74 Debug.Log( "Please assign a target to the camera that has a ThirdPersonController script attached." );
75
76
77 Cut( _target, centerOffset );
78 }
79
80 void DebugDrawStuff()
81 {
82 Debug.DrawLine( _target.position, _target.position + headOffset );
83
84 }
85
86 float AngleDistance( float a, float b )
87 {
88 a = Mathf.Repeat( a, 360 );
89 b = Mathf.Repeat( b, 360 );
90
91 return Mathf.Abs( b - a );
92 }
93
94 void Apply( Transform dummyTarget, Vector3 dummyCenter )
95 {
96 // Early out if we don't have a target
97 if( !controller )
98 return;
99
100 Vector3 targetCenter = _target.position + centerOffset;
101 Vector3 targetHead = _target.position + headOffset;
102
103 // DebugDrawStuff();
104
105 // Calculate the current & target rotation angles
106 float originalTargetAngle = _target.eulerAngles.y;
107 float currentAngle = cameraTransform.eulerAngles.y;
108
109 // Adjust real target angle when camera is locked
110 float targetAngle = originalTargetAngle;
111
112 // When pressing Fire2 (alt) the camera will snap to the target direction real quick.
113 // It will stop snapping when it reaches the target
114 if( Input.GetButton( "Fire2" ) )
115 snap = true;
116
117 if( snap )
118 {
119 // We are close to the target, so we can stop snapping now!
120 if( AngleDistance( currentAngle, originalTargetAngle ) < 3.0f )
121 snap = false;
122
123 currentAngle = Mathf.SmoothDampAngle( currentAngle, targetAngle, ref angleVelocity, snapSmoothLag, snapMaxSpeed );
124 }
125 // Normal camera motion
126 else
127 {
128 if( controller.GetLockCameraTimer() < lockCameraTimeout )
129 {
130 targetAngle = currentAngle;
131 }
132
133 // Lock the camera when moving backwards!
134 // * It is really confusing to do 180 degree spins when turning around.
135 if( AngleDistance( currentAngle, targetAngle ) > 160 && controller.IsMovingBackwards() )
136 targetAngle += 180;
137
138 currentAngle = Mathf.SmoothDampAngle( currentAngle, targetAngle, ref angleVelocity, angularSmoothLag, angularMaxSpeed );
139 }
140
141
142 // When jumping don't move camera upwards but only down!
143 if( controller.IsJumping() )
144 {
145 // We'd be moving the camera upwards, do that only if it's really high
146 float newTargetHeight = targetCenter.y + height;
147 if( newTargetHeight < targetHeight || newTargetHeight - targetHeight > 5 )
148 targetHeight = targetCenter.y + height;
149 }
150 // When walking always update the target height
151 else
152 {
153 targetHeight = targetCenter.y + height;
154 }
155
156 // Damp the height
157 float currentHeight = cameraTransform.position.y;
158 currentHeight = Mathf.SmoothDamp( currentHeight, targetHeight, ref heightVelocity, heightSmoothLag );
159
160 // Convert the angle into a rotation, by which we then reposition the camera
161 Quaternion currentRotation = Quaternion.Euler( 0, currentAngle, 0 );
162
163 // Set the position of the camera on the x-z plane to:
164 // distance meters behind the target
165 cameraTransform.position = targetCenter;
166 cameraTransform.position += currentRotation * Vector3.back * distance;
167
168 // Set the height of the camera
169 cameraTransform.position = new Vector3( cameraTransform.position.x, currentHeight, cameraTransform.position.z );
170
171 // Always look at the target
172 SetUpRotation( targetCenter, targetHead );
173 }
174
175 void LateUpdate()
176 {
177 Apply( transform, Vector3.zero );
178 }
179
180 void Cut( Transform dummyTarget, Vector3 dummyCenter )
181 {
182 float oldHeightSmooth = heightSmoothLag;
183 float oldSnapMaxSpeed = snapMaxSpeed;
184 float oldSnapSmooth = snapSmoothLag;
185
186 snapMaxSpeed = 10000;
187 snapSmoothLag = 0.001f;
188 heightSmoothLag = 0.001f;
189
190 snap = true;
191 Apply( transform, Vector3.zero );
192
193 heightSmoothLag = oldHeightSmooth;
194 snapMaxSpeed = oldSnapMaxSpeed;
195 snapSmoothLag = oldSnapSmooth;
196 }
197
198 void SetUpRotation( Vector3 centerPos, Vector3 headPos )
199 {
200 // Now it's getting hairy. The devil is in the details here, the big issue is jumping of course.
201 // * When jumping up and down we don't want to center the guy in screen space.
202 // This is important to give a feel for how high you jump and avoiding large camera movements.
203 //
204 // * At the same time we dont want him to ever go out of screen and we want all rotations to be totally smooth.
205 //
206 // So here is what we will do:
207 //
208 // 1. We first find the rotation around the y axis. Thus he is always centered on the y-axis
209 // 2. When grounded we make him be centered
210 // 3. When jumping we keep the camera rotation but rotate the camera to get him back into view if his head is above some threshold
211 // 4. When landing we smoothly interpolate towards centering him on screen
212 Vector3 cameraPos = cameraTransform.position;
213 Vector3 offsetToCenter = centerPos - cameraPos;
214
215 // Generate base rotation only around y-axis
216 Quaternion yRotation = Quaternion.LookRotation( new Vector3( offsetToCenter.x, 0, offsetToCenter.z ) );
217
218 Vector3 relativeOffset = Vector3.forward * distance + Vector3.down * height;
219 cameraTransform.rotation = yRotation * Quaternion.LookRotation( relativeOffset );
220
221 // Calculate the projected center position and top position in world space
222 Ray centerRay = m_CameraTransformCamera.ViewportPointToRay( new Vector3( 0.5f, 0.5f, 1 ) );
223 Ray topRay = m_CameraTransformCamera.ViewportPointToRay( new Vector3( 0.5f, clampHeadPositionScreenSpace, 1 ) );
224
225 Vector3 centerRayPos = centerRay.GetPoint( distance );
226 Vector3 topRayPos = topRay.GetPoint( distance );
227
228 float centerToTopAngle = Vector3.Angle( centerRay.direction, topRay.direction );
229
230 float heightToAngle = centerToTopAngle / ( centerRayPos.y - topRayPos.y );
231
232 float extraLookAngle = heightToAngle * ( centerRayPos.y - centerPos.y );
233 if( extraLookAngle < centerToTopAngle )
234 {
235 extraLookAngle = 0;
236 }
237 else
238 {
239 extraLookAngle = extraLookAngle - centerToTopAngle;
240 cameraTransform.rotation *= Quaternion.Euler( -extraLookAngle, 0, 0 );
241 }
242 }
243
244 Vector3 GetCenterOffset()
245 {
246 return centerOffset;
247 }
248
249 }
The distance in the x-z plane to the target
the height we want the camera to be above the target
Early out if we don't have a target
DebugDrawStuff();
Calculate the current & target rotation angles
Adjust real target angle when camera is locked
When pressing Fire2 (alt) the camera will snap to the target direction real quick.
It will stop snapping when it reaches the target
We are close to the target, so we can stop snapping now!
Normal camera motion
Lock the camera when moving backwards!
* It is really confusing to do 180 degree spins when turning around.
When jumping don't move camera upwards but only down!
We'd be moving the camera upwards, do that only if it's really high
When walking always update the target height
Damp the height
Convert the angle into a rotation, by which we then reposition the camera
Set the position of the camera on the x-z plane to:
distance meters behind the target
Set the height of the camera
Always look at the target
Now it's getting hairy. The devil is in the details here, the big issue is jumping of course.
* When jumping up and down we don't want to center the guy in screen space.
This is important to give a feel for how high you jump and avoiding large camera movements.
* At the same time we dont want him to ever go out of screen and we want all rotations to be totally smooth.
So here is what we will do:
1. We first find the rotation around the y axis. Thus he is always centered on the y-axis
2. When grounded we make him be centered
3. When jumping we keep the camera rotation but rotate the camera to get him back into view if his head is above some threshold
4. When landing we smoothly interpolate towards centering him on screen
Generate base rotation only around y-axis
Calculate the projected center position and top position in world space